#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <ostream>
#include <queue>
#include "InfoAnalizer.h"
#include "Program.h"
#include "CommandCreator.h"

using namespace std;

int Program::getId() {
  return id;
}

void Program::resetProgram() {
  workedInQuant = false;
}  

AbstractCommand *getCommand(const std::string &command) {
  static CommandCreator creator;
  return creator.getCommand(command);
}

//id_ - program id (bigger 0)  
Program::Program(int id_, std::list<std::string>::const_iterator &start, const std::list<std::string>::const_iterator &end) {
  std::transform(start, end, back_inserter(commands), &getCommand);
  id = id_;
}

bool Program::isFinished() {  
  return (commands.empty());
}  

void Program::makeTimeQuant(std::deque<int> &nextBlockCand, int &lockId, IVariableDict *variables, std::ostream &outStream) {    
  if (workedInQuant) {
    return;
  }
  workedInQuant = true;
  int quantSize = InfoAnalizer::getTimeQuantumSize();
  for (int i = 0; (i < quantSize) && (commands.size() > 0);) {
    AbstractCommand *curCommand = commands.front();
//    std::string commandText = curCommand->getCommand();
    i += curCommand->getTime();
    if (curCommand->execute(variables, id, lockId, nextBlockCand, outStream)) {
      delete curCommand;
      commands.pop_front();
    } else {
      return;
    }        
  }
}